package cz.cvut.fel.taskpro.data.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.OrderColumn;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;


/**
 * This entity represents student type of user. Extends from {@linkplain TaskProUser}.
 * Student could be member of team, could have assignmet to complate and could be member
 * of study group.
 * 
 * @author Tom
 * @version 1.0.0 beta
 */
@Entity
@Table(name = "student")
@DiscriminatorValue(value = "student")
@PrimaryKeyJoinColumn(name = "id")
@NamedQueries({
    // @NamedQuery(name = "TaskProUser.findByLogin", query = "SELECT u FROM TaskProUser u WHERE u.login = :login"),
    @NamedQuery(name = "Student.all", query = "SELECT s FROM Student s"),
    @NamedQuery(name = "Student.findByKantor", query = "SELECT DISTINCT s FROM Student s JOIN s.mGroups p WHERE p.kantor = :kantor"),
    @NamedQuery(name = "Student.findByGroup", query = "SELECT DISTINCT s FROM Student s WHERE s.mGroups =:groupTaskPro"),
    @NamedQuery(name = "Student.findByTeam", query = "SELECT DISTINCT s FROM Student s WHERE s.team =:team")
})
public class Student extends TaskProUser implements Serializable {

    private static final long serialVersionUID = 1L;
    @OneToMany(mappedBy = "student", cascade = {CascadeType.REFRESH, CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST})
    //@OrderBy("dateOfSubmit ASC")
    private List<AssignmentSubmit> mAssignmentSubmit;
    @ManyToMany(cascade = {CascadeType.REFRESH, CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST})
    @OrderBy("dateOfAssignment ASC")
    private List<Assignment> mAssignment;
    @ManyToMany(mappedBy = "mStudents", cascade = {CascadeType.REFRESH, CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST})
    private List<GroupTaskPro> mGroups;
    @ManyToMany(cascade = {CascadeType.REFRESH, CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST})
    @OrderBy("name ASC")
    private List<Team> team;
    @OneToMany(mappedBy = "submittedStudent", cascade = {CascadeType.REFRESH, CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST})
    private List<Version> mVersions;

    public List<Team> getTeam() {
        return team;
    }

    public void setTeam(List<Team> team) {
        this.team = team;
    }

    public void setmAssignmentSubmit(List<AssignmentSubmit> mAssignmentSubmit) {

        this.mAssignmentSubmit = mAssignmentSubmit;
    }

    @OrderColumn(name = "code")
    public List<GroupTaskPro> getmGroups() {
        return mGroups;
    }

    public void setmGroups(List<GroupTaskPro> mGroups) {
        this.mGroups = mGroups;
    }

    public Student() {
    }

    /**
     * prida studentovi novou paralelku
     *
     * @param p - nova paralelka
     */
    public void addParalelka(GroupTaskPro p) {
        if (this.mGroups == null) {
            mGroups = new ArrayList<GroupTaskPro>();
        }
        mGroups.add(p);
    }

    public void addTeam(Team t) {
        if (this.team == null) {
            this.team = new ArrayList<Team>();
        }
        team.add(t);
    }

    public void addAssingment(Assignment a) {
        if (this.mAssignment == null) {
            this.mAssignment = new ArrayList<Assignment>();
        }
        mAssignment.add(a);
    }

    /**
     * prida studentovi novy ukol
     *
     * @param u - novy ukol
     */
    public void addUkol(AssignmentSubmit u) {
        if (mAssignmentSubmit == null) {
            mAssignmentSubmit = new ArrayList<AssignmentSubmit>();
        }
        mAssignmentSubmit.add(u);
        u.setStudent(this);
    }

    public void addVersion(Version versionToAdd) {
        if (mVersions == null) {
            mVersions = new ArrayList<Version>();
        }
        mVersions.add(versionToAdd);

    }

    public List<AssignmentSubmit> getmAssignmentSubmit() {
        return mAssignmentSubmit;
    }

    public List<Assignment> getmAssignment() {
        return mAssignment;
    }

    public void setmAssignment(List<Assignment> mAssignment) {
        this.mAssignment = mAssignment;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Student)) {
            return false;
        }
        Student other = (Student) object;
        if (getId() != other.getId()) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (int) getId();
        return hash;
    }

    @Override
    public String toString() {
        return "DL.entity.Student[ id=" + getId() + " login=" + getLogin() + " ]";
    }

    public List<cz.cvut.fel.taskpro.data.entity.Version> getmVersions() {
        return mVersions;
    }

    public void setmVersions(List<cz.cvut.fel.taskpro.data.entity.Version> mVersions) {
        this.mVersions = mVersions;
    }

    public void removeAssignment(Assignment assignmentToRemove) {
        if (mAssignment == null) {
            return;
        }
        mAssignment.remove(assignmentToRemove);
    }
}